//
//  BlocksAndClosuresTest.m
//  test_simple_project
//
//  块(Block)和闭包语法特性测试实现
//

#import "BlocksAndClosuresTest.h"

// 全局常量定义
NSString * const BlockTestNotificationName = @"BlockTestNotification";
NSString * const BlockTestErrorDomain = @"BlockTestErrorDomain";

// 全局Block变量定义
BasicBlock GlobalBasicBlock;
ParameterBlock GlobalParameterBlock;
ReturnBlock GlobalReturnBlock;

@interface BlocksAndClosuresTest ()

// 私有属性
@property (strong, nonatomic) NSMutableArray<BasicBlock> *registeredCallbacks;
@property (strong, nonatomic) NSMutableDictionary<NSString *, NSMutableArray<ParameterBlock> *> *eventHandlers;
@property (strong, nonatomic) dispatch_queue_t blockQueue;

@end

@implementation BlocksAndClosuresTest

- (instancetype)init {
    self = [super init];
    if (self) {
        _registeredCallbacks = [[NSMutableArray alloc] init];
        _eventHandlers = [[NSMutableDictionary alloc] init];
        _blockQueue = dispatch_queue_create("com.test.block.queue", DISPATCH_QUEUE_CONCURRENT);
        
        // 初始化Block属性
        _basicBlockProperty = ^{
            NSLog(@"基础Block属性执行");
        };
        
        _parameterBlockProperty = ^(NSString *parameter) {
            NSLog(@"参数Block属性执行，参数: %@", parameter);
        };
        
        _returnBlockProperty = ^NSString *(NSString *input) {
            return [NSString stringWithFormat:@"返回Block处理: %@", input];
        };
        
        _completionBlockProperty = ^(BOOL success, NSError *error) {
            if (success) {
                NSLog(@"完成Block: 操作成功");
            } else {
                NSLog(@"完成Block: 操作失败 - %@", error.localizedDescription);
            }
        };
    }
    return self;
}

#pragma mark - Block作为参数的方法实现

- (void)executeBasicBlock:(BasicBlock)block {
    NSLog(@"准备执行基础Block");
    EXECUTE_BLOCK_SAFELY(block);
    NSLog(@"基础Block执行完成");
}

- (void)executeParameterBlock:(ParameterBlock)block withParameter:(NSString *)parameter {
    NSLog(@"准备执行参数Block，参数: %@", parameter);
    EXECUTE_BLOCK_SAFELY(block, parameter);
    NSLog(@"参数Block执行完成");
}

- (NSString *)executeReturnBlock:(ReturnBlock)block withInput:(NSString *)input {
    NSLog(@"准备执行返回Block，输入: %@", input);
    if (block) {
        NSString *result = block(input);
        NSLog(@"返回Block执行完成，结果: %@", result);
        return result;
    }
    return nil;
}

- (void)performAsyncOperationWithCompletion:(CompletionBlock)completion {
    NSLog(@"开始异步操作");
    
    dispatch_async(self.blockQueue, ^{
        // 模拟异步操作
        [NSThread sleepForTimeInterval:1.0];
        
        // 随机成功或失败
        BOOL success = arc4random_uniform(2) == 0;
        NSError *error = nil;
        
        if (!success) {
            error = [NSError errorWithDomain:BlockTestErrorDomain 
                                        code:2001 
                                    userInfo:@{NSLocalizedDescriptionKey: @"异步操作失败"}];
        }
        
        // 在主队列执行完成回调
        EXECUTE_BLOCK_ON_MAIN_QUEUE(completion, success, error);
    });
}

- (void)performLongRunningTaskWithProgress:(ProgressBlock)progress 
                                completion:(CompletionBlock)completion {
    NSLog(@"开始长时间运行任务");
    
    dispatch_async(self.blockQueue, ^{
        for (int i = 0; i <= 10; i++) {
            float progressValue = i / 10.0f;
            NSString *status = [NSString stringWithFormat:@"处理步骤 %d/10", i];
            
            // 报告进度
            EXECUTE_BLOCK_ON_MAIN_QUEUE(progress, progressValue, status);
            
            // 模拟工作
            [NSThread sleepForTimeInterval:0.2];
        }
        
        // 任务完成
        EXECUTE_BLOCK_ON_MAIN_QUEUE(completion, YES, nil);
    });
}

#pragma mark - 数据处理Block方法实现

- (NSArray *)filterArray:(NSArray *)array withPredicate:(PredicateBlock)predicate {
    if (!predicate) return array;
    
    NSMutableArray *filtered = [[NSMutableArray alloc] init];
    for (id object in array) {
        if (predicate(object)) {
            [filtered addObject:object];
        }
    }
    return [filtered copy];
}

- (NSArray *)mapArray:(NSArray *)array withTransform:(TransformBlock)transform {
    if (!transform) return array;
    
    NSMutableArray *mapped = [[NSMutableArray alloc] init];
    for (id object in array) {
        id transformed = transform(object);
        if (transformed) {
            [mapped addObject:transformed];
        }
    }
    return [mapped copy];
}

- (id)reduceArray:(NSArray *)array withInitialValue:(id)initialValue reducer:(ReduceBlock)reducer {
    if (!reducer) return initialValue;
    
    id accumulator = initialValue;
    for (id object in array) {
        accumulator = reducer(accumulator, object);
    }
    return accumulator;
}

- (NSArray *)sortArray:(NSArray *)array withComparator:(ComparatorBlock)comparator {
    if (!comparator) return array;
    
    return [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return comparator(obj1, obj2);
    }];
}

- (NSArray *)sortedArrayUsingBlock:(NSArray *)array {
    return [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        if ([obj1 respondsToSelector:@selector(compare:)]) {
            return [obj1 compare:obj2];
        }
        return NSOrderedSame;
    }];
}

#pragma mark - Block作为返回值的方法实现

- (BasicBlock)createBasicBlock {
    return ^{
        NSLog(@"动态创建的基础Block执行");
    };
}

- (ParameterBlock)createParameterBlockWithPrefix:(NSString *)prefix {
    return ^(NSString *parameter) {
        NSLog(@"%@: %@", prefix, parameter);
    };
}

- (ReturnBlock)createReturnBlockWithSuffix:(NSString *)suffix {
    return ^NSString *(NSString *input) {
        return [NSString stringWithFormat:@"%@%@", input, suffix];
    };
}

- (PredicateBlock)createPredicateBlockForClass:(Class)targetClass {
    return ^BOOL(id object) {
        return [object isKindOfClass:targetClass];
    };
}

- (CompletionBlock)createCompletionBlockWithSuccessMessage:(NSString *)successMessage {
    return ^(BOOL success, NSError *error) {
        if (success) {
            NSLog(@"成功: %@", successMessage);
        } else {
            NSLog(@"失败: %@", error.localizedDescription);
        }
    };
}

- (TransformBlock)createTransformBlockWithOperation:(NSString *)operation {
    if ([operation isEqualToString:@"uppercase"]) {
        return ^id(id input) {
            if ([input isKindOfClass:[NSString class]]) {
                return [input uppercaseString];
            }
            return input;
        };
    } else if ([operation isEqualToString:@"reverse"]) {
        return ^id(id input) {
            if ([input isKindOfClass:[NSString class]]) {
                NSString *string = (NSString *)input;
                NSMutableString *reversed = [[NSMutableString alloc] init];
                for (NSInteger i = string.length - 1; i >= 0; i--) {
                    [reversed appendString:[string substringWithRange:NSMakeRange(i, 1)]];
                }
                return [reversed copy];
            }
            return input;
        };
    }
    
    return ^id(id input) {
        return input; // 默认不变换
    };
}

#pragma mark - 嵌套Block方法实现

- (void)executeNestedBlock:(NestedBlock)nestedBlock {
    if (!nestedBlock) return;
    
    nestedBlock(^(NSString *result) {
        NSLog(@"嵌套Block内部执行，结果: %@", result);
    });
}

- (void)chainBlocks:(BasicBlock)firstBlock second:(BasicBlock)secondBlock {
    NSLog(@"开始Block链式执行");
    
    if (firstBlock) {
        firstBlock();
        NSLog(@"第一个Block执行完成");
    }
    
    if (secondBlock) {
        secondBlock();
        NSLog(@"第二个Block执行完成");
    }
    
    NSLog(@"Block链式执行完成");
}

- (void)executeBlockSequence:(NSArray<BasicBlock> *)blocks {
    NSLog(@"开始执行Block序列，共 %lu 个Block", (unsigned long)blocks.count);
    
    for (NSUInteger i = 0; i < blocks.count; i++) {
        BasicBlock block = blocks[i];
        NSLog(@"执行第 %lu 个Block", (unsigned long)(i + 1));
        EXECUTE_BLOCK_SAFELY(block);
    }
    
    NSLog(@"Block序列执行完成");
}

#pragma mark - Block变量修饰符测试实现

- (void)demonstrateBlockVariableModifiers {
    NSLog(@"演示Block变量修饰符");
    
    // __block变量可以在Block内部修改
    __block NSInteger blockVariable = 0;
    
    // 普通变量在Block内部只能读取
    NSInteger normalVariable = 10;
    
    BasicBlock modifierBlock = ^{
        // 可以修改__block变量
        blockVariable = 100;
        
        // 可以读取普通变量，但不能修改
        NSLog(@"普通变量值: %ld", (long)normalVariable);
        NSLog(@"__block变量修改后的值: %ld", (long)blockVariable);
    };
    
    NSLog(@"执行前 __block变量值: %ld", (long)blockVariable);
    modifierBlock();
    NSLog(@"执行后 __block变量值: %ld", (long)blockVariable);
}

- (NSInteger)countWithBlockVariable:(NSArray *)array {
    __block NSInteger count = 0;
    
    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        count++; // 修改__block变量
        NSLog(@"处理第 %lu 个对象: %@", (unsigned long)idx, obj);
    }];
    
    return count;
}

- (void)modifyExternalVariableWithBlock {
    __block NSMutableString *externalString = [[NSMutableString alloc] initWithString:@"初始值"];
    
    ParameterBlock modifyBlock = ^(NSString *parameter) {
        [externalString appendString:parameter]; // 修改外部__block变量
    };
    
    NSLog(@"修改前: %@", externalString);
    modifyBlock(@" - 添加内容1");
    modifyBlock(@" - 添加内容2");
    NSLog(@"修改后: %@", externalString);
}

#pragma mark - 高级Block用法实现

- (void)registerCallback:(BasicBlock)callback {
    if (callback) {
        [self.registeredCallbacks addObject:[callback copy]];
        NSLog(@"注册回调，当前回调数量: %lu", (unsigned long)self.registeredCallbacks.count);
    }
}

- (void)triggerRegisteredCallbacks {
    NSLog(@"触发所有注册的回调，共 %lu 个", (unsigned long)self.registeredCallbacks.count);

    for (BasicBlock callback in self.registeredCallbacks) {
        EXECUTE_BLOCK_SAFELY(callback);
    }
}

- (void)addEventListener:(NSString *)eventName handler:(ParameterBlock)handler {
    if (!eventName || !handler) return;

    NSMutableArray *handlers = self.eventHandlers[eventName];
    if (!handlers) {
        handlers = [[NSMutableArray alloc] init];
        self.eventHandlers[eventName] = handlers;
    }

    [handlers addObject:[handler copy]];
    NSLog(@"为事件 '%@' 添加处理器，当前处理器数量: %lu", eventName, (unsigned long)handlers.count);
}

- (void)removeEventListener:(NSString *)eventName {
    if (eventName) {
        [self.eventHandlers removeObjectForKey:eventName];
        NSLog(@"移除事件 '%@' 的所有处理器", eventName);
    }
}

- (void)triggerEvent:(NSString *)eventName withData:(NSString *)data {
    NSArray *handlers = self.eventHandlers[eventName];
    if (handlers.count > 0) {
        NSLog(@"触发事件 '%@'，数据: %@，处理器数量: %lu", eventName, data, (unsigned long)handlers.count);

        for (ParameterBlock handler in handlers) {
            EXECUTE_BLOCK_SAFELY(handler, data);
        }
    } else {
        NSLog(@"事件 '%@' 没有注册的处理器", eventName);
    }
}

- (NSArray *)functionalProgrammingDemo:(NSArray *)numbers {
    NSLog(@"函数式编程演示，输入数组: %@", numbers);

    // 过滤：只保留偶数
    NSArray *evenNumbers = [self filterArray:numbers withPredicate:^BOOL(id object) {
        if ([object isKindOfClass:[NSNumber class]]) {
            return [object integerValue] % 2 == 0;
        }
        return NO;
    }];
    NSLog(@"过滤后的偶数: %@", evenNumbers);

    // 映射：每个数乘以2
    NSArray *doubledNumbers = [self mapArray:evenNumbers withTransform:^id(id object) {
        if ([object isKindOfClass:[NSNumber class]]) {
            return @([object integerValue] * 2);
        }
        return object;
    }];
    NSLog(@"映射后的数组: %@", doubledNumbers);

    // 归约：计算总和
    NSNumber *sum = [self reduceArray:doubledNumbers
                     withInitialValue:@0
                              reducer:^id(id accumulator, id object) {
        if ([accumulator isKindOfClass:[NSNumber class]] && [object isKindOfClass:[NSNumber class]]) {
            return @([accumulator integerValue] + [object integerValue]);
        }
        return accumulator;
    }];
    NSLog(@"归约后的总和: %@", sum);

    return @[evenNumbers, doubledNumbers, sum];
}

- (NSDictionary *)groupArray:(NSArray *)array byKey:(NSString *(^)(id object))keyExtractor {
    if (!keyExtractor) return @{};

    NSMutableDictionary *groups = [[NSMutableDictionary alloc] init];

    for (id object in array) {
        NSString *key = keyExtractor(object);
        if (key) {
            NSMutableArray *group = groups[key];
            if (!group) {
                group = [[NSMutableArray alloc] init];
                groups[key] = group;
            }
            [group addObject:object];
        }
    }

    return [groups copy];
}

#pragma mark - Block内存管理实现

- (void)demonstrateBlockMemoryManagement {
    NSLog(@"演示Block内存管理");

    // 强引用循环示例（不推荐）
    __block BlocksAndClosuresTest *strongSelf = self;
    BasicBlock strongReferenceBlock = ^{
        NSLog(@"强引用Block访问: %@", strongSelf.description);
        strongSelf = nil; // 通过__block修饰符可以修改
    };

    // 弱引用模式（推荐）
    __weak typeof(self) weakSelf = self;
    BasicBlock weakReferenceBlock = ^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf) {
            NSLog(@"弱引用Block访问: %@", strongSelf.description);
        } else {
            NSLog(@"对象已被释放");
        }
    };

    strongReferenceBlock();
    weakReferenceBlock();
}

- (void)demonstrateWeakSelfPattern {
    NSLog(@"演示弱引用self模式");

    WEAK_SELF;

    [self performAsyncOperationWithCompletion:^(BOOL success, NSError *error) {
        STRONG_SELF;
        if (!strongSelf) {
            NSLog(@"对象已被释放，取消操作");
            return;
        }

        if (success) {
            NSLog(@"异步操作成功，对象仍然存在: %@", strongSelf.description);
        } else {
            NSLog(@"异步操作失败: %@", error.localizedDescription);
        }
    }];
}

- (void)demonstrateStrongWeakDance {
    NSLog(@"演示强弱引用舞蹈模式");

    __weak typeof(self) weakSelf = self;

    dispatch_async(self.blockQueue, ^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;

        NSLog(@"第一步：获得强引用");

        dispatch_async(dispatch_get_main_queue(), ^{
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (!strongSelf) return;

            NSLog(@"第二步：在主队列中再次获得强引用");

            [strongSelf performAsyncOperationWithCompletion:^(BOOL success, NSError *error) {
                NSLog(@"第三步：完成回调，强引用自动释放");
            }];
        });
    });
}

@end

#pragma mark - 全局Block函数实现

BasicBlock CreateGlobalBasicBlock(void) {
    return ^{
        NSLog(@"全局创建的基础Block执行");
    };
}

ParameterBlock CreateGlobalParameterBlock(NSString *prefix) {
    return ^(NSString *parameter) {
        NSLog(@"全局参数Block: %@%@", prefix, parameter);
    };
}

ReturnBlock CreateGlobalReturnBlock(NSString *suffix) {
    return ^NSString *(NSString *input) {
        return [NSString stringWithFormat:@"%@%@", input, suffix];
    };
}

void ExecuteGlobalBlock(BasicBlock block) {
    NSLog(@"全局函数执行Block");
    EXECUTE_BLOCK_SAFELY(block);
}

NSArray *FilterGlobalArray(NSArray *array, PredicateBlock predicate) {
    if (!predicate) return array;

    NSMutableArray *filtered = [[NSMutableArray alloc] init];
    for (id object in array) {
        if (predicate(object)) {
            [filtered addObject:object];
        }
    }
    return [filtered copy];
}

void PerformGlobalAsyncOperation(CompletionBlock completion) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 模拟异步操作
        [NSThread sleepForTimeInterval:0.5];

        EXECUTE_BLOCK_ON_MAIN_QUEUE(completion, YES, nil);
    });
}

#pragma mark - BlockUtilities实现

@implementation BlockUtilities

static NSMutableDictionary *blockCache;

+ (void)initialize {
    if (self == [BlockUtilities class]) {
        blockCache = [[NSMutableDictionary alloc] init];
    }
}

+ (PredicateBlock)isKindOfClassBlock:(Class)targetClass {
    return ^BOOL(id object) {
        return [object isKindOfClass:targetClass];
    };
}

+ (PredicateBlock)isEqualToObjectBlock:(id)targetObject {
    return ^BOOL(id object) {
        return [object isEqual:targetObject];
    };
}

+ (TransformBlock)stringTransformBlock:(NSString *)operation {
    if ([operation isEqualToString:@"uppercase"]) {
        return ^id(id input) {
            if ([input isKindOfClass:[NSString class]]) {
                return [input uppercaseString];
            }
            return input;
        };
    } else if ([operation isEqualToString:@"lowercase"]) {
        return ^id(id input) {
            if ([input isKindOfClass:[NSString class]]) {
                return [input lowercaseString];
            }
            return input;
        };
    }

    return ^id(id input) {
        return input;
    };
}

+ (ComparatorBlock)stringComparatorBlock {
    return ^NSComparisonResult(id obj1, id obj2) {
        if ([obj1 isKindOfClass:[NSString class]] && [obj2 isKindOfClass:[NSString class]]) {
            return [obj1 compare:obj2];
        }
        return NSOrderedSame;
    };
}

+ (PredicateBlock)andPredicateBlock:(PredicateBlock)first second:(PredicateBlock)second {
    return ^BOOL(id object) {
        return first(object) && second(object);
    };
}

+ (PredicateBlock)orPredicateBlock:(PredicateBlock)first second:(PredicateBlock)second {
    return ^BOOL(id object) {
        return first(object) || second(object);
    };
}

+ (PredicateBlock)notPredicateBlock:(PredicateBlock)predicate {
    return ^BOOL(id object) {
        return !predicate(object);
    };
}

+ (void)cacheBlock:(id)block forKey:(NSString *)key {
    if (block && key) {
        blockCache[key] = [block copy];
    }
}

+ (id)cachedBlockForKey:(NSString *)key {
    return blockCache[key];
}

+ (void)clearBlockCache {
    [blockCache removeAllObjects];
}

@end
